/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.gemom.combinationItems;

import java.util.*;
import com.gemom.*;
/**
 *
 * @author Yair Diaz
 */
public class SearchCombinations {

    	private int numbercombinationsAdded=0;
	private BidNode sroot;	
	private int M = 1;
	private int B=0;
	private int A=3;
	private int []stopMask;
	private int []prevsm;
	private Bid btroot;
	private double maxVolumeBroker;//will hold the max revenue path value
        public int visits=0;
        
        private Vector<Bid> listBids;
        private Vector<Vector<Item>> combisItems;
	
					   
    public SearchCombinations(Item[] arrayItems,double maxVolumeBroker){
	
        //Holds the combinations found
        this.combisItems=new Vector<Vector<Item>>();
        this.maxVolumeBroker=maxVolumeBroker;
        
        this.listBids=listBids = new Vector<Bid>();
			for(int i=0;i<arrayItems.length;i++)
				listBids.add(new Bid(i));
        for(int i=0;i<arrayItems.length;i++)
            listBids.get(i).addItem(arrayItems[i]);
        
        Vector<Item> fixedItemVector=this.getFixedItemVector();
        for(int i=0;i<listBids.size();i++){
        listBids.get(i).setItemflags(fixedItemVector.size(), fixedItemVector);
        }

        BidTree bt = new BidTree(listBids);
	this.btroot= bt.getBidTreeRoot();
        
        //Creating stopMask for pruning the bid tree
        this.stopMask = new int[arrayItems.length];
	for(int i=0;i<stopMask.length;i++)stopMask[i]=A;
	this.prevsm=new int[arrayItems.length];
	for(int i=0;i<prevsm.length;i++)prevsm[i]=0;
	
        //Creating root node for SearchCombinations
        this.sroot = new BidNode();
			
        //Recursive method: Generation of the SearchCombinations
         searchInOrder(btroot,stopMask,0,sroot,prevsm);  
         
       //adding single-item combinations
         for(int i=0;i<arrayItems.length;i++)
                if(arrayItems[i].getItemRate()<=maxVolumeBroker)
                    {   Vector<Item> newCombi=new Vector<Item>();
                        newCombi.add(arrayItems[i]);
                        this.combisItems.add(newCombi);
                        numbercombinationsAdded++;
                    }
         
        }
    //Recursive method: Generation and exploration of SearchCombinations
    public void searchtree(Bid node, int []stopMask,BidNode bidnode,int[] prevsm){
		
	visits++;
        
        bidnode.getbch().add(new BidNode(node));
        
         if(bidnode.getbch().size()>1)bidnode.getbch().removeElementAt(0);////\/\/\/\/\optimisation
        
	bidnode= bidnode.getbch().lastElement();   
		
	BidNode bn2=sroot.getbch().lastElement();
	Bid aBid=bn2.getBid();
        
////////////////////////////////////////////////////////////////////////////////     
        double sum=0.0;
        boolean f1=true;
        while(!bn2.getbch().isEmpty())
        {
            Vector<Item> newCombi=new Vector<Item>();
            
            while(!bn2.getbch().isEmpty())
             {  
               for(int i=0;i<aBid.getItemsVec().size();i++)
               {
                   sum+=aBid.getItemsVec().get(i).getItemRate();///obtains the itemRate[double]
                   if(sum<=maxVolumeBroker)newCombi.add(aBid.getItemsVec().get(i));
                   else{f1=false;break;}
               }
               if(f1==true)bn2=bn2.getbch().lastElement();aBid=bn2.getBid();
               if(f1==true)
               if(bn2.getbch().isEmpty())
               {
                    for(int i=0;i<aBid.getItemsVec().size();i++)
                    {
                        sum+=aBid.getItemsVec().get(i).getItemRate();///obtains the itemRate[double]
                        if(sum<=maxVolumeBroker)newCombi.add(aBid.getItemsVec().get(i));
                        else{f1=false;break;}
                   }
               }
            if(f1==false)break;
            }
            if(f1==true){combisItems.add(newCombi);
                        numbercombinationsAdded++;}
            else{break;}
         
        }
 ///////////////////////////////////////////////////////////////////////////////
       
	//setting the stopMask	
	int[]smclone= stopMask.clone();
	int[]prevsmc= prevsm.clone();
        
        //if f1==false    there was a break of loop
         if(f1==false)for(int i=0;i<prevsmc.length;i++)prevsmc[i]=1;////god
        
        
	for(int i=0;i<node.getItemflags().length;i++)prevsmc[i]=prevsmc[i]|node.getItemflags()[i];
	//discarding items in between the paths
	////////////////////////
	for(int i=0;i<prevsmc.length;i++)
	{if(prevsmc[i]==1)for(int j=0;j<i;j++){prevsmc[j]=1;}}
	/////////////////////////
	for(int i=0;i<prevsmc.length;i++)
            {if(prevsmc[i]==0){smclone[i]=A;}
	   	    else if(prevsmc[i]==1)smclone[i]=B;}
		  
	searchInOrder(btroot,smclone,0,bidnode,prevsmc);				  
	
}

    public void searchInOrder(Bid node, int []stopMask,int sm, BidNode bidnode,int[] prevsm) {
		
        if(sm<stopMask.length )
        {
            if(stopMask[sm]==M)
            {
               if(node!=null)node=node.left;
               if(sm==stopMask.length-1 && node!=null )
			{ //System.out.println(node+"a");
                            searchtree(node,stopMask,bidnode,prevsm);
			}
		searchInOrder(node,stopMask,++sm,bidnode,prevsm);
            }
            else if(stopMask[sm]==B )
            {
                    if(node!=null)node=node.right;
		    if(sm==stopMask.length-1 && node!=null )
			{//System.out.println(node+"b");
                            searchtree(node,stopMask,bidnode,prevsm);
			}
                searchInOrder(node,stopMask,++sm,bidnode,prevsm);	
            }
            else if(stopMask[sm]==A)
            {
		Bid v1 = node;
		int sm1 = sm;
			
		if(node!=null)node=node.left;
	  	if(sm==stopMask.length-1 && node!=null)
                        { //System.out.println(node+"c");
                            searchtree(node,stopMask,bidnode,prevsm); 
                        }
		searchInOrder(node,stopMask,++sm,bidnode,prevsm);
			
		if(v1!=null)node=v1.right;        
		if(sm1==stopMask.length-1 && v1!=null && node!=null)
                        {//System.out.println(node+"d");
                            searchtree(node,stopMask,bidnode,prevsm);	
                        }
		searchInOrder(node,stopMask,++sm1,bidnode,prevsm);
            }
	 }//end outer if		
    }//end method

    private Vector<Item> getFixedItemVector()
    {
        Vector<Item> fixdItemVec =new Vector<Item>();
        for(int i=0;i<listBids.size();i++)
        {   for(int j=0;j<listBids.get(i).getItemsVec().size();j++)
            {  if(!fixdItemVec.contains(listBids.get(i).getItemsVec().get(j)))
                    fixdItemVec.add(listBids.get(i).getItemsVec().get(j));
            }
        }
        return fixdItemVec;
    }
    public void printCombinations()
    {
        for(int i=0;i<this.combisItems.size();i++)
        { for(int j=0;j<this.combisItems.get(i).size();j++) 
          {  System.out.print(this.combisItems.get(i).get(j)+","); }
          System.out.println();
        }
    }
    
    public int getNumberCombinations(){return numbercombinationsAdded;}
    
    public Vector<Vector<Item>>  getCombinations(){return combisItems;}
  
    /*
    public void printstree(BidNode bidnode)
    {
 	  for(int i=0;i<bidnode.getbch().size();i++){
 		System.out.println(bidnode.getbch().get(i).getBid());
 	 	printstree(bidnode.getbch().get(i));}		
    
    }//end method
 */
}